﻿using System;
using System.Linq.Expressions;

namespace Tszy.Unlimited.Data.AdoNet.Sql.Components
{
    /// <summary>
    ///
    /// </summary>
    public interface IQuery : ICloneable
    {
        /// <summary>
        /// 表达式上下文。
        /// </summary>
        public ExpressionContext Context { get; }
    }

    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="TSource"></typeparam>
    public interface IQuery<TSource> :
        IEnumerableQuery<TSource>,
        IIdentityQuery<TSource>
    {
        /// <summary>
        /// 转换成集合搜索。
        /// </summary>
        /// <remarks>
        /// 即：生成一个子查询。
        /// </remarks>
        /// <returns></returns>
        IEnumerableQuery<TSource> ToEnumerableQuery();
    }

    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="TSource"></typeparam>
    public interface IIdentityQuery<TSource>
    {
        /// <summary>
        /// 设置本次查询的唯一标识。
        /// </summary>
        /// <param name="identity">唯一标识。</param>
        /// <returns></returns>
        IQuery<TSource> SetIdentity(string identity);
    }

    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="TSource"></typeparam>
    public interface IEnumerableQuery<TSource> :
        IQuery,
        IWhereQuery<TSource>,
        ITakeQuery<TSource>,
        ISkipQuery<TSource>,
        IOrderByQuery<TSource>,
        ISelectQuery<TSource>,
        ICountQuery<TSource>,
        IExecuteQuery<TSource>
    {
    }

    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="TSource"></typeparam>
    public interface IEnumerableTaskQuery<TSource> :
        IQuery,
        ISkipQuery_1<TSource>,
        ISelectQuery<TSource>,
        ICountQuery<TSource>,
        IExecuteQuery<TSource>
    {
    }

    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="TSource"></typeparam>
    public interface IEnumerableSkipQuery<TSource> :
        IQuery,
        ITakeQuery_1<TSource>,
        ISelectQuery<TSource>,
        ICountQuery<TSource>,
        IExecuteQuery<TSource>
    {
    }

    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="TSource"></typeparam>
    public interface IEnumerableSelectQuery<TSource> :
        IQuery,
        ISelectQuery<TSource>,
        ICountQuery<TSource>,
        IExecuteQuery<TSource>
    {
    }

    /// <summary>
    /// 统计查询器。
    /// </summary>
    /// <typeparam name="TSource">数据实体类型。</typeparam>
    public interface ICountQuery<TSource> : IQuery
    {
        #region 元素是否存在

        /// <summary>
        /// 元素是否存在。
        /// </summary>
        /// <returns>存在则返回 True，否则返回 False。</returns>
        bool Any();

        /// <summary>
        /// 元素是否存在。
        /// </summary>
        /// <param name="predicate">条件。</param>
        /// <returns>存在则返回 True，否则返回 False。</returns>
        bool Any(Expression<Func<TSource, bool>> predicate);

        #endregion 元素是否存在

        #region 元素个数

        /// <summary>
        /// 获得元素个数。
        /// </summary>
        /// <returns>元素个数。</returns>
        int Count();

        /// <summary>
        /// 获得元素个数。
        /// </summary>
        /// <param name="predicate">条件。</param>
        /// <returns>元素个数。</returns>
        int Count(Expression<Func<TSource, bool>> predicate);

        #endregion 元素个数

        #region 指定字段累加总数

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        int Sum(Expression<Func<TSource, int>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        int? Sum(Expression<Func<TSource, int?>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        long Sum(Expression<Func<TSource, long>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        long? Sum(Expression<Func<TSource, long?>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        double Sum(Expression<Func<TSource, double>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        double? Sum(Expression<Func<TSource, double?>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        float Sum(Expression<Func<TSource, float>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        float? Sum(Expression<Func<TSource, float?>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        decimal Sum(Expression<Func<TSource, decimal>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        decimal? Sum(Expression<Func<TSource, decimal?>> selector);

        #endregion 指定字段累加总数

        #region 指定字段平均数

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        double Average(Expression<Func<TSource, int>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        double? Average(Expression<Func<TSource, int?>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        double Average(Expression<Func<TSource, long>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        double? Average(Expression<Func<TSource, long?>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        double Average(Expression<Func<TSource, double>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        double? Average(Expression<Func<TSource, double?>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        float Average(Expression<Func<TSource, float>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        float? Average(Expression<Func<TSource, float?>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        decimal Average(Expression<Func<TSource, decimal>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        decimal? Average(Expression<Func<TSource, decimal?>> selector);

        #endregion 指定字段平均数

        #region 最小值

        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="selector"></param>
        /// <returns></returns>
        TResult Min<TResult>(Expression<Func<TSource, TResult>> selector);

        #endregion 最小值

        #region 最大值

        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="selector"></param>
        /// <returns></returns>
        TResult Max<TResult>(Expression<Func<TSource, TResult>> selector);

        #endregion 最大值
    }

    /// <summary>
    /// 排序查询器。
    /// </summary>
    /// <typeparam name="TSource">数据实体类型。</typeparam>
    public interface IOrderByQuery<TSource> : IQuery
    {
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="TKey"></typeparam>
        /// <param name="keySelector"></param>
        /// <returns></returns>
        IThenOrderByQuery<TSource> OrderBy<TKey>(Expression<Func<TSource, TKey>> keySelector);

        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="TKey"></typeparam>
        /// <param name="keySelector"></param>
        /// <returns></returns>
        IThenOrderByQuery<TSource> OrderByDescending<TKey>(Expression<Func<TSource, TKey>> keySelector);
    }

    /// <summary>
    /// 连续排序查询器。
    /// </summary>
    /// <typeparam name="TSource">数据实体类型。</typeparam>
    public interface IThenOrderByQuery<TSource> :
        IQuery,
        ITakeQuery<TSource>,
        ISkipQuery<TSource>,
        ISelectQuery<TSource>,
        ICountQuery<TSource>,
        IExecuteQuery<TSource>
    {
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="TKey"></typeparam>
        /// <param name="keySelector"></param>
        /// <returns></returns>
        IThenOrderByQuery<TSource> ThenBy<TKey>(Expression<Func<TSource, TKey>> keySelector);

        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="TKey"></typeparam>
        /// <param name="keySelector"></param>
        /// <returns></returns>
        IThenOrderByQuery<TSource> ThenByDescending<TKey>(Expression<Func<TSource, TKey>> keySelector);
    }

    /// <summary>
    /// 字段过虑查询器。
    /// </summary>
    /// <typeparam name="TSource">数据实体类型。</typeparam>
    public interface ISelectQuery<TSource> : IQuery
    {
        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        IExecuteQuery<short> Select(Expression<Func<TSource, short>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        IExecuteQuery<short?> Select(Expression<Func<TSource, short?>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        IExecuteQuery<int> Select(Expression<Func<TSource, int>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        IExecuteQuery<int?> Select(Expression<Func<TSource, int?>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        IExecuteQuery<long> Select(Expression<Func<TSource, long>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        IExecuteQuery<long?> Select(Expression<Func<TSource, long?>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        IExecuteQuery<float> Select(Expression<Func<TSource, float>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        IExecuteQuery<float?> Select(Expression<Func<TSource, float?>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        IExecuteQuery<double> Select(Expression<Func<TSource, double>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        IExecuteQuery<double?> Select(Expression<Func<TSource, double?>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        IExecuteQuery<decimal> Select(Expression<Func<TSource, decimal>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        IExecuteQuery<decimal?> Select(Expression<Func<TSource, decimal?>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        IExecuteQuery<bool> Select(Expression<Func<TSource, bool>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        IExecuteQuery<bool?> Select(Expression<Func<TSource, bool?>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        IExecuteQuery<char> Select(Expression<Func<TSource, char>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        IExecuteQuery<string> Select(Expression<Func<TSource, string>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        IExecuteQuery<DateTime> Select(Expression<Func<TSource, DateTime>> selector);

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        IExecuteQuery<TResult> Select<TResult>(Expression<Func<TSource, TResult>> selector) where TResult : class, new();

        /// <summary>
        ///
        /// </summary>
        /// <param name="selector"></param>
        /// <returns></returns>
        IExecuteQuery<object> Select(Expression<Func<TSource, object>> selector);
    }

    /// <summary>
    /// 条件处理器。
    /// </summary>
    /// <typeparam name="TSource">数据实体类型。</typeparam>
    public interface IWhereQuery<TSource> : IQuery
    {
        /// <summary>
        /// 条件过滤。
        /// </summary>
        /// <param name="predicate">条件。</param>
        /// <returns>查询器。</returns>
        IEnumerableQuery<TSource> Where(Expression<Func<TSource, bool>> predicate);
    }

    /// <summary>
    /// 集合元素查询器。
    /// </summary>
    /// <typeparam name="TSource">数据实体类型。</typeparam>
    public interface ITakeQuery<TSource> : IQuery
    {
        /// <summary>
        /// 从序列的开头返回指定数量的连续元素。
        /// </summary>
        /// <param name="count">要返回的元素数量。</param>
        /// <returns>查询器。</returns>
        IEnumerableTaskQuery<TSource> Take(int count);
    }

    /// <summary>
    /// 集合元素查询器。
    /// </summary>
    /// <typeparam name="TSource">数据实体类型。</typeparam>
    public interface ITakeQuery_1<TSource> : IQuery
    {
        /// <summary>
        /// 从序列的开头返回指定数量的连续元素。
        /// </summary>
        /// <param name="count">要返回的元素数量。</param>
        /// <returns>查询器。</returns>
        IEnumerableSelectQuery<TSource> Take(int count);
    }

    /// <summary>
    /// 集合元素查询器。
    /// </summary>
    /// <typeparam name="TSource">数据实体类型。</typeparam>
    public interface ISkipQuery<TSource> : IQuery
    {
        /// <summary>
        /// 跳过序列中指定数量的元素，然后返回剩余的元素。
        /// </summary>
        /// <param name="count">返回剩余元素前要跳过的元素数量。</param>
        /// <returns>查询器。</returns>
        IEnumerableSkipQuery<TSource> Skip(int count);
    }

    /// <summary>
    /// 集合元素查询器。
    /// </summary>
    /// <typeparam name="TSource">数据实体类型。</typeparam>
    public interface ISkipQuery_1<TSource> : IQuery
    {
        /// <summary>
        /// 跳过序列中指定数量的元素，然后返回剩余的元素。
        /// </summary>
        /// <param name="count">返回剩余元素前要跳过的元素数量。</param>
        /// <returns>查询器。</returns>
        IEnumerableSelectQuery<TSource> Skip(int count);
    }

    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="TResult"></typeparam>
    public interface ISelectEnumerableQuery<TResult> :
        IQuery,
        IEnumerableQuery<TResult>
    {
    }

    #region 关联查询

    ///// <summary>
    /////
    ///// </summary>
    ///// <typeparam name="TSource"></typeparam>
    //public interface IJoinQuery<TSource> : IQuery
    //{
    //    /// <summary>
    //    ///
    //    /// </summary>
    //    /// <typeparam name="TTarget"></typeparam>
    //    /// <param name="predicate"></param>
    //    /// <returns></returns>
    //    IJoinEnumerableQuery<TSource, TTarget> InnerJoin<TTarget>(Expression<Func<TSource, TTarget, bool>> predicate) where TTarget : new();

    //    /// <summary>
    //    ///
    //    /// </summary>
    //    /// <typeparam name="TTarget"></typeparam>
    //    /// <param name="predicate"></param>
    //    /// <returns></returns>
    //    IJoinEnumerableQuery<TSource, TTarget> LeftJoin<TTarget>(Expression<Func<TSource, TTarget, bool>> predicate) where TTarget : new();
    //}

    ///// <summary>
    /////
    ///// </summary>
    ///// <typeparam name="TSource"></typeparam>
    ///// <typeparam name="TTarget"></typeparam>
    //public interface IJoinSelectQuery<TSource, TTarget>
    //{
    //    /// <summary>
    //    /// 过滤搜索出来的字段。
    //    /// </summary>
    //    /// <typeparam name="TResult"></typeparam>
    //    /// <param name="selector"></param>
    //    /// <returns></returns>
    //    IJoinSelectExecuteQuery<TSource, TTarget, TResult> Select<TResult>(Expression<Func<TTarget, TResult>> selector) where TResult : class, new();
    //}

    ///// <summary>
    /////
    ///// </summary>
    ///// <typeparam name="TSource"></typeparam>
    ///// <typeparam name="TTarget"></typeparam>
    //public interface IJoinEnumerableQuery<TSource, TTarget> :
    //    IQuery,
    //    IJoinQuery<TSource>,
    //    IJoinSelectQuery<TSource, TTarget>
    //{
    //}

    ///// <summary>
    /////
    ///// </summary>
    ///// <typeparam name="TSource"></typeparam>
    ///// <typeparam name="TTarget"></typeparam>
    ///// <typeparam name="TResult"></typeparam>
    //public interface IJoinSelectExecuteQuery<TSource, TTarget, TResult> :
    //    IQuery,
    //    IQuery<TSource>
    //{
    //    /// <summary>
    //    /// INNER JOIN 语句。
    //    /// </summary>
    //    /// <typeparam name="TNewTarget"></typeparam>
    //    /// <param name="predicate"></param>
    //    /// <returns></returns>
    //    IJoinEnumerableQuery<TSource, TTarget, TNewTarget, TResult> InnerJoin<TNewTarget>(Expression<Func<TSource, TTarget, TNewTarget, bool>> predicate) where TNewTarget : new();

    //    /// <summary>
    //    /// LEFT JOIN 语句。
    //    /// </summary>
    //    /// <typeparam name="TNewTarget"></typeparam>
    //    /// <param name="predicate"></param>
    //    /// <returns></returns>
    //    IJoinEnumerableQuery<TSource, TTarget, TNewTarget, TResult> LeftJoin<TNewTarget>(Expression<Func<TSource, TTarget, TNewTarget, bool>> predicate) where TNewTarget : new();
    //}

    ///// <summary>
    ///// JOIN 集合查询对象。
    ///// </summary>
    ///// <typeparam name="TSource"></typeparam>
    ///// <typeparam name="TTarget"></typeparam>
    ///// <typeparam name="TNewTarget"></typeparam>
    ///// <typeparam name="TResult"></typeparam>
    //public interface IJoinEnumerableQuery<TSource, TTarget, TNewTarget, TResult> :
    //    IQuery,
    //    IJoinSelectQuery<TSource, TNewTarget>
    //{
    //}

    #endregion 关联查询
}